package controller

import (
	"bufio"
	"container/heap"
	"fmt"
	"github.com/gin-gonic/gin"
	"math"
	"os"
	"pure/app/utils"
	"strconv"
	"strings"
	"sync"
	"time"
)

type ht struct {
	landJx map[string]struct{}
	landCl map[string]struct{}
}

var Ht = ht{}

type HtAStarReq struct {
	Start []float64 `json:"start"`
	End   []float64 `json:"end"`
}

type Config struct {
	Motions [][2]float64
}

//var cellP = 1000.0

// var landMap = AllWhiteIntTest(120.0879, 36.2606, 0.0001, cellP)
// var landMap = AllWhiteIntTest(116, 38, 0.0001, cellP)
var landMap = make(map[[2]int]struct{}, 200000)
var gangkouMap = readGangkouMap()

// var landMapBig = AllWhiteIntTest(116, 38, 0.001, 1000)
var landMapBig = readLandTxt("./public/image/0.001.txt")

//var bufferMap = readLandTxt("./public/image/buffer.txt")

var bufferMapXiao = readLandTxt("./public/image/buffer_xiao.txt")
var bufferMapTu = readLandTxt("./public/image/buffer_tu.txt")
var txtM = sync.Mutex{}

var items [][]float64

var angleArr []float64

// 由于有分段的设计，找一段的方法抽出来
func findOnePath(req HtAStarReq, angleNum int, step float64, isOut bool, isEndBuffer bool, first bool) []string {
	cellP := 10000.0
	if !isOut {
		cellP = 10000.0
	}
	costMap := map[[2]int]float64{
		[2]int{
			int(math.Round(req.Start[0] * cellP)),
			int(math.Round(req.Start[1] * cellP)),
		}: 0,
	}
	relationMap := map[[2]int][3]int{
		[2]int{
			int(math.Round(req.Start[0] * cellP)),
			int(math.Round(req.Start[1] * cellP)),
		}: [3]int{
			int(math.Round(req.Start[0] * cellP)),
			int(math.Round(req.Start[1] * cellP)),
			0,
		},
	}

	closeMap := map[[2]int]int{}

	grayMap := make(map[[2]int]int, 200000)
	openList := &MinHeap{}
	heap.Init(openList)
	heap.Push(openList, []float64{0, req.Start[0], req.Start[1], -1})

	motions := GetMotions(angleNum)
	num := 0
	//var items [][3]float64
	for {
		//num++
		allNum++
		//取出open中的最小值，每次计算一个当前点与终点的方向当作动态方向
		minItem := heap.Pop(openList).([]float64)
		closeMap[[2]int{
			int(math.Round(minItem[1] * cellP)),
			int(math.Round(minItem[2] * cellP)),
		}] = 1
		items = append(items, minItem)
		if minItem[3] > 0 {
			idxArr[int(minItem[3])]++
		}

		angle := math.Atan2(req.End[0]-minItem[1], req.End[1]-minItem[2])
		anglePai := angle * 180 / math.Pi
		if anglePai < 0 {
			anglePai += 360
		}

		latD := 0.0
		lonD := 0.0
		if anglePai > 45 && anglePai < 135 {
			latD = 1.0
			lonD = latD / math.Tan(angle)
			//area = 0
		} else if anglePai > 135 && anglePai < 225 {
			lonD = -1.0
			latD = -math.Tan(angle)
		} else if anglePai > 225 && anglePai < 315 {
			latD = -1.0
			lonD = latD / math.Tan(angle)
		} else {
			lonD = 1.0
			latD = math.Tan(angle)
		}

		l := math.Sqrt(math.Pow(latD, 2) + math.Pow(lonD, 2))
		if isOut {
			motions[0] = []float64{lonD, latD, l}
			//motions[0] = []float64{9999, 9999, l * 9999}

		} else {
			//motions[0] = []float64{9999, 9999, l * 9999}
			motions[0] = []float64{lonD, latD, l}
		}

		//latS, lonS := 1.0, 1.0
		//if req.End[0]-minItem[1] < 0 {
		//	latS = -1.0
		//}
		//if req.End[1]-minItem[2] < 0 {
		//	lonS = -1.0
		//}
		//
		//latD, lonD := utils.FindClosestFraction(math.Abs((req.End[0]-minItem[1])/(req.End[1]-minItem[2])), 2)
		//latDF, lonDF := float64(latD)*0.5*latS, float64(lonD)*0.5*lonS
		//
		//if latDF > 4.0 {
		//	latDF = 1.0
		//	lonDF = 0.0
		//}
		//if lonDF > 4.0 {
		//	latDF = 0.0
		//	lonDF = 1.0
		//}
		//l := math.Sqrt(math.Pow(latDF, 2) + math.Pow(lonDF, 2))
		//
		//if isOut {
		//	motions[0] = []float64{latDF, lonDF, l}
		//
		//} else {
		//	motions[0] = []float64{9999, 9999, l * 9999}
		//}

		//motions[0] = []float64{lonD, latD, l}
		//motions[0] = []float64{9999, 9999, l}

		//motions[0] = []float64{lonD, latD, l}
		//fmt.Println(motions[0])

		//t3 := time.Now().UnixNano()
		//_ = GetMotions(32)
		//t33 := time.Now().UnixNano()
		//allT3 += int(t33 - t3)

		//l := math.Sqrt(math.Cos(angle) + math.Sin(angle))
		//motions[0] = []float64{math.Cos(angle), math.Sin(angle), l}

		//每隔5000个报数一次
		if num%50000 == 0 {
			fmt.Println("heap推出了:", num)
		}
		//距离终点的距离足够近，退出循环
		//time.Sleep(time.Second)
		if math.Abs(minItem[1]-req.End[0]) < 0.01 && math.Abs(minItem[2]-req.End[1]) < 0.01 {
			path := getPath(relationMap, [2]int{int(math.Round(req.Start[0] * cellP)), int(math.Round(req.Start[1] * cellP))}, [2]int{int(math.Round(minItem[1] * cellP)), int(math.Round(minItem[2] * cellP))}, [2]int{int(math.Round(req.End[0] * cellP)), int(math.Round(req.End[1] * cellP))}, cellP, first, isOut)
			fmt.Println("heap推出的可能的点数:", num)
			return path
		}

		//if isOut {
		//	paintGray(minItem, grayMap, step, 0.0001)
		//}
		//fmt.Println(minItem)
		//time.Sleep(time.Second)

		for idx, sN := range getNeighbor(minItem, motions, grayMap, step, isOut, costMap, closeMap, cellP, first, &req) {

			if sN[0] < 800 {
				num++
				latInt := int(math.Round(sN[0] * cellP))
				lonInt := int(math.Round(sN[1] * cellP))

				////作用不大
				//_, isClose := closeMap[[2]int{
				//	latInt, lonInt,
				//}]
				//if isClose {
				//	continue
				//}

				minLatInt := int(math.Round(minItem[1] * cellP))
				minLonInt := int(math.Round(minItem[2] * cellP))

				//l:=motions[idx][2]*step
				ll := math.Sqrt(math.Pow(minItem[1]-sN[0], 2) + math.Pow(minItem[2]-sN[1], 2))

				newCost := costMap[[2]int{
					minLatInt, minLonInt,
				}] + ll

				_, ok := costMap[[2]int{
					latInt, lonInt,
				}]

				if !ok {
					costMap[[2]int{
						latInt, lonInt,
					}] = 999.0
				}

				if newCost < costMap[[2]int{
					latInt, lonInt,
				}] {
					costMap[[2]int{
						latInt, lonInt,
					}] = newCost
					relationMap[[2]int{
						latInt, lonInt,
					}] = [3]int{minLatInt, minLonInt, idx}
					heap.Push(openList, []float64{newCost + getDistance(req.End[0], req.End[1], sN[0], sN[1]), sN[0], sN[1], float64(idx)})

					//fmt.Println("newCost:", newCost, "getDistanceWeight:", getDistanceWeight(req.End[0], req.End[1], sN[0], sN[1], minItem), newCost+getDistanceWeight(req.End[0], req.End[1], sN[0], sN[1], minItem), idx)
					//heap.Push(openList, []float64{newCost + getDistanceWeight(req.End[0], req.End[1], sN[0], sN[1], minItem, angleArr), sN[0], sN[1], float64(idx)})
				}

			}

		}

	}
}

var idxArr [17]int

// HtAStar 开始
func (ctl *ht) HtAStar(c *gin.Context) {
	items = [][]float64{}
	allNum = 0
	at1 := time.Now().UnixNano()
	var req HtAStarReq
	_ = c.ShouldBind(&req)
	//打印起始点和目标点
	fmt.Println("起始点---->", req.Start, "目标点---->", req.End)
	step := 0.006
	angleNum := 32
	//bufferSize := 0.01

	allT1 = 0
	allT2 = 0
	allT3 = 0
	idxArr = [17]int{}
	//找到缓冲区外的点
	t1 := time.Now().UnixNano()
	startBuffer, endBuffer := getPointBuffer(&req, step*1.2)
	t11 := time.Now().UnixNano()
	fmt.Println("冲出缓冲区用时：", (t11-t1)/1e6, "毫秒")

	//_, isBuffer := bufferMap[[2]int{
	//	int(endBuffer[0]*100 + 1),
	//	int(endBuffer[1] * 100),
	//}]

	var pathStart, pathEnd, pathMid, PathResult []string
	var pathWg sync.WaitGroup
	if startBuffer[0] != req.Start[0] || startBuffer[1] != req.Start[1] {
		go func() {
			pathWg.Add(1)
			//t2 := time.Now().UnixNano()
			var reqStart HtAStarReq
			reqStart.Start = req.Start
			reqStart.End = startBuffer
			_, islll := gangkouMap[[2]int{
				int(req.Start[0] * 10000),
				int(req.Start[1] * 10000),
			}]

			if islll {
				//fmt.Println(getNotLan(req.Start, req.End))
				reqStart.Start = getNotLan(req.Start, req.End)
			}
			pathStart = findOnePath(reqStart, angleNum, 0.0006, false, true, true)
			pathStart = append(pathStart, utils.Float64ToFixedStr(req.Start[0], 4)+","+utils.Float64ToFixedStr(req.Start[1], 4))
			//t22 := time.Now().UnixNano()
			//fmt.Println("起始点用时：", (t22-t2)/1e6)
			pathWg.Done()
		}()
	}

	if endBuffer[0] != req.End[0] || endBuffer[1] != req.End[1] {
		go func() {
			pathWg.Add(1)
			var reqEnd HtAStarReq
			reqEnd.Start = endBuffer
			reqEnd.End = req.End
			pathEnd = findOnePath(reqEnd, angleNum, 0.001, false, true, true)
			pathWg.Done()
		}()
	}

	t4 := time.Now().UnixNano()
	var reqMid HtAStarReq
	reqMid.Start = startBuffer
	reqMid.End = endBuffer
	pathMid = findOnePath(reqMid, angleNum, step, true, false, true)
	t44 := time.Now().UnixNano()
	fmt.Println("中间点用时：", (t44-t4)/1e6)
	//fmt.Println("获取邻域：", allT1/1e6)
	//fmt.Println("mmm：", allT2/1e6)
	//fmt.Println("关顾：", idxArr)
	//fmt.Println("特殊点：", inNum)
	fmt.Println("maxAngle:", maxAngle)
	if len(pathStart) != 0 {
		pathMid = pathMid[:len(pathMid)-2]
	}

	//pathMid = utils.AddArc(pathMid)
	//pathMid = utils.SmoothBezier(pathMid)
	pathWg.Wait()
	PathResult = append(PathResult, pathEnd...)
	PathResult = append(PathResult, pathMid...)
	PathResult = append(PathResult, pathStart...)

	at2 := time.Now().UnixNano()
	c.JSON(200, gin.H{
		"code": 0,
		"msg":  "成功",
		"data": gin.H{
			"lines":       PathResult,
			"startBuffer": startBuffer,
			"endBuffer":   endBuffer,
			"t":           (at2 - at1) / 1e6,
			"num":         allNum,
			"gdNum":       len(pathMid) + len(pathStart) + len(pathEnd),
			"items":       items,
		},
	})
}

var jpsArr = [][]int{{}}

//var jpsArr = []map[int]int{
//	{
//		9:  1,
//		11: 1,
//		12: 1,
//		13: 1,
//		14: 2,
//		15: 2,`
//	},
//}

func GetMotions8(angle int) [][]float64 {
	var motions [][]float64 = [][]float64{{1, 0}, {1, 1}, {0, 1}, {-1, 1}, {-1, 0}, {-1, -1}, {0, -1}, {1, -1}}
	return motions
}

// GetMotions 获取n方向
func GetMotions(angle int) [][]float64 {
	var motions [][]float64
	motions = append(motions, []float64{})
	//m32 := [][]float64{{1, 0.25}, {0.75, 0.5}, {0.5, 0.75}, {0.25, 1}, {-0.25, 1}, {-0.5, 0.75}, {-0.75, 0.5}, {-1, 0.25}, {-1, -0.25}, {-0.75, -0.5}, {-0.5, -0.75}, {-0.25, -1}, {0.25, -1}, {0.5, -0.75}, {0.75, -0.5}, {1, -0.25}}
	////m32 := [][]float64{{0.25, 1}, {0.5, 0.75}, {0.75, 0.5}, {1, 0.25}, {1, -0.25}, {0.75, -0.5}, {0.5, -0.75}, {0.25, -1}, {-0.25, -1}, {-0.5, -0.75}, {-0.75, -0.5}, {-1, -0.25}, {-1, 0.25}, {-0.75, 0.5}, {-0.5, 0.75}, {-0.25, 1}}
	//m16 := [][]float64{{0.25, 0.5}, {0.5, 0.25}, {0.5, -0.25}, {0.25, -0.5}, {-0.25, -0.5}, {-0.5, -0.25}, {-0.5, 0.25}, {-0.25, 0.5}}
	//m8 := [][]float64{{0, 0.25}, {0.25, 0.25}, {0.25, 0}, {0.25, -0.25}, {0, -0.25}, {-0.25, -0.25}, {-0.25, 0}, {-0.25, 0.25}}
	//
	////将m32,m16,m8合并
	//motions = append(motions, m32...)
	//motions = append(motions, m16...)
	//motions = append(motions, m8...)
	//
	//for i, v := range motions {
	//	if i == 0 {
	//		continue
	//	} else {
	//		l := math.Sqrt(math.Pow(v[0], 2) + math.Pow(v[1], 2))
	//		motions[i] = append(motions[i], l)
	//	}
	//}

	//文献参考的m16
	//m16 := [][]float64{{0, 0.5}, {0.5, 1}, {0.5, 0.5}, {1, 0.5}, {0.5, 0}, {1, -0.5}, {0.5, -0.5}, {0.5, -1}, {0, -0.5}, {-0.5, -1}, {-0.5, -0.5}, {-1, -0.5}, {-0.5, 0}, {-1, 0.5}, {-0.5, 0.5}, {-0.5, 1}}
	//正常用这个
	m16 := [][]float64{{1, 0.5}, {0.5, 1}, {-0.5, 1}, {-1, 0.5}, {-1, -0.5}, {-0.5, -1}, {0.5, -1}, {1, -0.5}, {0.5, 0}, {0.5, 0.5}, {0, 0.5}, {-0.5, 0.5}, {-0.5, 0}, {-0.5, -0.5}, {0, -0.5}, {0.5, -0.5}}
	//m8 := [][]float64{{0, 1}, {1, 1}, {1, 0}, {1, -1}, {0, -1}, {-1, -1}, {-1, 0}, {-1, 1}}
	//m24 := [][]float64{{1, 0.5}, {0.5, 1}, {-0.5, 1}, {-1, 0.5}, {-1, -0.5}, {-0.5, -1}, {0.5, -1}, {1, -0.5}, {1, 0}, {-1, 0}, {0, 1}, {0, -1}, {0.5, 0}, {0.5, 0.5}, {0, 0.5}, {-0.5, 0.5}, {-0.5, 0}, {-0.5, -0.5}, {0, -0.5}, {0.5, -0.5}}

	//外圈24

	//m16 := [][]float64{{1, 0}, {1, 0.5}, {1, 1}, {0.5, 1}, {0, 1}, {-0.5, 1}, {-1, 1}, {-1, 0.5}, {-1, 0}, {-1, -0.5}, {-1, -1}, {-0.5, -1}, {0, -1}, {0.5, -1}, {1, -1}, {1, -0.5}}
	//m16 := [][]float64{{0, 1}, {0.5, 1}, {1, 1}, {1, 0.5}, {1, 0}, {1, -0.5}, {1, -1}, {0.5, -1}, {0, -1}, {-0.5, -1}, {-1, -1}, {-1, -0.5}, {-1, 0}, {-1, 0.5}, {-1, 1}, {-0.5, 1}}
	//m32 := [][]float64{{0, 1}, {0.25, 1}, {0.5, 1}, {0.75, 1}, {1, 1}, {1, 0.75}, {1, 0.5}, {1, 0.25}, {1, 0}, {1, -0.25}, {1, -0.5}, {1, -0.75}, {1, -1}, {0.75, -1}, {0.5, -1}, {0.25, -1}, {0, -1}, {-0.25, -1}, {-0.5, -1}, {-0.75, -1}, {-1, -1}, {-1, -0.75}, {-1, -0.5}, {-1, -0.25}, {-1, 0}, {-1, 0.25}, {-1, 0.5}, {-1, 0.75}, {-1, 1}, {-0.75, 1}, {-0.5, 1}, {-0.25, 1}}
	////m1 := [][]float64{{1, 0}, {1, 0.25}, {1, 0.5}, {1, 0.75}, {0.75, 1}, {0.5, 1}, {0.25, 1}, {0, 1}, {-0.25, 1}, {-0.5, 1}, {-0.75, 1}, {-1, 1}, {-1, 0.75}, {-1, 0.5}, {-1, 0.25}, {-1, 0}, {-1, -0.25}, {-1, -0.5}, {-1, -0.75}, {-1, -1}, {-0.75, -1}, {-0.5, -1}, {-0.25, -1}, {0, -1}, {0.25, -1}, {0.5, -1}, {0.75, -1}, {1, -1}, {1, -0.75}, {1, -0.5}, {1, -0.25}}
	for _, v := range m16 {
		l := math.Sqrt(math.Pow(v[0], 2) + math.Pow(v[1], 2))
		motions = append(motions, []float64{v[0], v[1], l})
	}

	//offset := 8/angle
	//point8 := [][]float64{{0, 1}, {1, 1}, {1, 0}, {1, -1}, {0, -1}, {-1, -1}, {-1, 0}, {-1, 1}, {0, 1}}
	//idx := 0
	//for {
	//	if idx == 8 {
	//		break
	//	}
	//	latLonIdx := 0
	//	point := point8[idx]
	//	if math.Abs(point8[idx][0]) != 1 || math.Abs(point8[idx+1][0]) != 1 {
	//		latLonIdx = 0
	//		point = []float64{point8[idx][0], point8[idx][1]}
	//	} else if math.Abs(point8[idx][1]) != 1 || math.Abs(point8[idx+1][1]) != 1 {
	//		latLonIdx = 1
	//	} else {
	//		idx++
	//	}
	//}
	//for
	//for i:=0;i<angle/8;i++ {
	//	for j:=1;j<=angle/8
	//}
	//return motions
	//for i := 0; i < angle; i++ {
	//	motions = append(motions, []float64{math.Cos(float64(i) * 2 * math.Pi / float64(angle)), math.Sin(float64(i) * 2 * math.Pi / float64(angle))})
	//}
	return motions

	//返回矩形32方向
	//return [][2]float64{{1, 0}, {1, 0.25}, {1, 0.5}, {1, 0.75}, {0.75, 1}, {0.5, 1}, {0.25, 1}, {0, 1}, {-0.25, 1}, {-0.5, 1}, {-0.75, 1}, {-1, 1}, {-1, 0.75}, {-1, 0.5}, {-1, 0.25}, {-1, 0}, {-1, -0.25}, {-1, -0.5}, {-1, -0.75}, {-1, -1}, {-0.75, -1}, {-0.5, -1}, {-0.25, -1}, {0, -1}, {0.25, -1}, {0.5, -1}, {0.75, -1}, {1, -1}, {1, -0.75}, {1, -0.5}, {1, -0.25}}
}

func GetMotions1(numDirections int) [][]float64 {
	directions := make([][]float64, numDirections)

	for i := 0; i < numDirections; i++ {
		angle := 2 * math.Pi * float64(i) / float64(numDirections)
		x := math.Cos(angle)
		y := math.Sin(angle)
		l := math.Sqrt(math.Pow(x, 2) + math.Pow(y, 2))
		directions[i] = []float64{x, y, l}
	}
	return directions
}

// MinHeap 小顶堆
type MinHeap [][]float64

func (h MinHeap) Len() int      { return len(h) }
func (h MinHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
func (h MinHeap) Less(i, j int) bool {
	return h[i][0] < h[j][0]
} // 小顶堆
func (h *MinHeap) Push(x interface{}) {
	*h = append(*h, x.([]float64))
}
func (h *MinHeap) Pop() interface{} {
	old := *h
	n := len(old)
	x := old[n-1]
	*h = old[0 : n-1]
	return x
}

func (h *MinHeap) downHeap(index int) {
	n := len(*h)
	for {
		childIndex := 2*index + 1
		if childIndex >= n {
			break
		}

		if childIndex+1 < n && (*h)[childIndex+1][0] < (*h)[childIndex][0] {
			childIndex++
		}

		if (*h)[index][0] <= (*h)[childIndex][0] {
			break
		}

		// 交换当前节点和子节点
		(*h).Swap(index, childIndex)
		index = childIndex
	}
}

func includesNumber(number, target, tolerance int) bool {
	//diff := math.Abs(number - target)
	//return diff <= tolerance

	return math.Abs(float64(number)-float64(target)) <= float64(tolerance)
}

//func AllWhiteIntTest(minLng, maxLat, step float64, precision float64) map[[2]int]struct{} {
//	//120.38669616044902 120.08785992 36.260629574755185 35.96465704
//	wt := time.Now().UnixNano()
//	landM := make(map[[2]int]struct{})
//	f1, _ := os.Open("./public/image/qd.png")
//	//f1, _ := os.Open("./public/image/yh.png")
//
//	num := 0
//
//	defer f1.Close()
//	img1, _, _ := image.Decode(f1)
//
//	maxX, maxY := img1.Bounds().Max.X, img1.Bounds().Max.Y
//
//	wt1 := time.Now().UnixNano()
//	fmt.Println("用时：", (wt1-wt)/1e6)
//
//	//colorArr := [][3]uint32{}
//
//	for i := 0; i < maxX; i = i + (int(step * cellP)) {
//		for j := 0; j < maxY; j = j + (int(step * cellP)) {
//			r, g, b, _ := img1.At(i, j).RGBA()
//			num++
//
//			//isCunzai := false
//			//for _, v := range colorArr {
//			//	if r == v[0] && g == v[1] && b == v[2] {
//			//		isCunzai = true
//			//		break
//			//	}
//			//}
//			//if !isCunzai {
//			//	colorArr = append(colorArr, [3]uint32{r, g, b})
//			//}
//			if r == 0 && g == 0 && b == 0 {
//				continue
//			} else {
//
//				lng := float64(i)*0.0001 + minLng
//				lat := maxLat - float64(j)*0.0001
//				//保持先lat后lng
//				landM[[2]int{
//					int(math.Round(lat * precision)),
//					int(math.Round(lng * precision)),
//				}] = struct{}{}
//			}
//		}
//	}
//
//	fmt.Println(num)
//
//	return landM
//}

var grayNum = 0
var landNum = 0
var allNum = 0
var effectNum = 0

var allT1 = 0
var allT2 = 0
var allT3 = 0

var angleMap = map[int]int{
	1:  5,
	2:  6,
	3:  7,
	4:  8,
	5:  1,
	6:  2,
	7:  3,
	8:  4,
	9:  13,
	10: 14,
	11: 15,
	12: 16,
	13: 9,
	14: 10,
	15: 11,
	16: 12,
}

// 根据方向获取一个点的所有可以的邻居
func getNeighbor(minItem []float64, motions [][]float64, grayMap map[[2]int]int, step float64, isOut bool, costMap map[[2]int]float64, closeMap map[[2]int]int, cellP float64, first bool, req *HtAStarReq) [][]float64 {
	//lastIdx := int(minItem[3])
	//if lastIdx == 1 || lastIdx == 5 || lastIdx == 9 || lastIdx == 13 {
	//	//	遍历jpsArr[0][0]
	//	for _, v := range jpsArr[0] {
	//		idx := lastIdx - 1 + v
	//		if idx > 16 {
	//			idx = idx - 16
	//		}
	//		motions[idx] = []float64{-10, 0, 0}
	//	}
	//} else if lastIdx == 2 || lastIdx == 4 || lastIdx == 6 || lastIdx == 8 || lastIdx == 10 || lastIdx == 12 || lastIdx == 816 {
	//
	//}
	//var list [][2]float64
	list := make([][]float64, 0, 33)

	//precision := 100.0
	//gridNum := 10000

	//_, isBuffer := bufferMapXiao[[2]int{
	//	int(minItem[1]*1000 + 1),
	//	int(minItem[2] * 1000),
	//}]
	//if !isBuffer {
	//	//precision = 1000.0
	//	////step = 0.01
	//	gridNum = 500
	//	//step = 0.01
	//}

	t11 := time.Now().UnixNano()

	//fmt.Println(motions)
	//fmt.Println(weakMap)
	//fmt.Println(angleGUji)
	//time.Sleep(time.Second)
	ratio1 := 1.0
	n := 3
	//if !isOut {
	//	n = 4
	//}
	for idx, offset := range motions {

		if idx == 0 || !isOut {
			n = 4
		} else {
			n = 4
		}
		if offset[0] > 800 {
			list = append(list, []float64{999.0, 999.0})
			continue
		}

		//单独处理第一个点
		if idx == 0 && first {
			r := 1.0

			for {
				lat := minItem[1] + offset[1]*r*step
				lon := minItem[2] + offset[0]*r*step
				r = r + 1
				_, isLand := bufferMapXiao[[2]int{
					int(lat*1000 + 1),
					int(lon * 1000),
				}]
				if isLand {
					break
				} else {
					if math.Abs(lat-req.End[0]) < 0.01 && math.Abs(lon-req.End[1]) < 0.01 {
						list = append(list, []float64{utils.Float64Fixed(lat, n), utils.Float64Fixed(lon, n)})
						return list
					}
				}
			}
			list = append(list, []float64{999.0, 999.0})
			continue
		}

		//我也不太知道为啥放大之后效果更好!!! 现在知道了，只有在估计距离小于实际距离时候才可以达到整体最优
		lat := minItem[1] + offset[1]*step*ratio1
		lon := minItem[2] + offset[0]*step*ratio1

		//t2 := time.Now().UnixNano()

		latInt := int(math.Round(lat * cellP))
		lonInt := int(math.Round(lon * cellP))

		//？
		if first {
			_, isBuffer := bufferMapTu[[2]int{
				int(math.Round(lat * 100)),
				int(math.Round(lon * 100)),
			}]

			if !isBuffer && minItem[3] != 0 {
				list = append(list, []float64{999.0, 999.0})
				continue
			}
		}

		//作用不大
		_, isClose := closeMap[[2]int{
			latInt, lonInt,
		}]
		if isClose {
			list = append(list, []float64{999.0, 999.0})
			continue
		}

		_, ok := costMap[[2]int{
			latInt, lonInt,
		}]

		if ok {
			list = append(list, []float64{utils.Float64Fixed(lat, n), utils.Float64Fixed(lon, n)})
			continue
		}

		//只在中间那段用地图大格子
		isLand := false

		//isBufferXiao := false

		if isOut {

			_, isLand = landMapBig[[2]int{
				int(lat*1000 + 1),
				int(lon * 1000),
			}]

		} else {
			//_, isLand = gangkouMap[[2]int{
			//	int(lat * cellP),
			//	int(lon * cellP),
			//}]

			for _, v := range GetMotions8(8) {
				_, isLandTep := gangkouMap[[2]int{
					int(lat*10000 + v[1]*2),
					int(lon*10000 + v[0]*2),
				}]

				if isLandTep {
					isLand = true
					break
				}
			}

		}

		if !isLand {
			list = append(list, []float64{utils.Float64Fixed(lat, n), utils.Float64Fixed(lon, n)})
			//_, isGray := grayMap[[2]int{
			//	int(lat*precision + 1),
			//	int(lon * precision),
			//}]
			//
			//if !isGray {
			//
			//	//list = append(list, [2]float64{lat, lon})
			//	list = append(list, []float64{utils.Float64Fixed(lat, n), utils.Float64Fixed(lon, n)})
			//
			//	grayMap[[2]int{
			//		int(lat*precision + 1),
			//		int(lon * precision),
			//	}] = 0
			//
			//} else {
			//
			//	gray := grayMap[[2]int{
			//		int(lat*precision + 1),
			//		int(lon * precision),
			//	}]
			//
			//	if gray < gridNum {
			//		//list = append(list, [2]float64{lat, lon})
			//		list = append(list, []float64{utils.Float64Fixed(lat, n), utils.Float64Fixed(lon, n)})
			//		grayMap[[2]int{
			//			int(lat*precision + 1),
			//			int(lon * precision),
			//		}]++
			//
			//	} else {
			//		allT3++
			//		list = append(list, []float64{999.0, 999.0})
			//	}
			//
			//}
		} else {
			//冲出缓冲区了再严格判断，如果有一个点还在地图上，进判断距离陆地太近，直接退出
			if isOut {
				inNum++
				list = [][]float64{}
				break
			} else {
				list = append(list, []float64{999.0, 999.0})
			}

			//list = [][2]float64{}
			//
			//break
		}

	}
	if minItem[3] == 0 && isOut && len(list) != 0 {
		list = [][]float64{list[0]}
	}
	t12 := time.Now().UnixNano()
	allT1 += int(t12 - t11)

	//fmt.Println(len(list))
	//time.Sleep(time.Second)
	return list
}

func getNeighborY(minItem []float64, motions [][]float64, grayMap map[[2]int]int, step float64, isOut bool, costMap map[[2]int]float64, closeMap map[[2]int]int, cellP float64) [][]float64 {
	list := make([][]float64, 0, 33)
	ratio1 := 1.0
	n := 3
	if !isOut {
		n = 4
		//gridNum = 100
	}
	for _, offset := range motions {
		if offset[0] > 800 {
			list = append(list, []float64{999.0, 999.0})
			continue
		}
		//if idx == angleMap[int(minItem[3])] {
		//	list = append(list, [2]float64{999.0, 999.0})
		//	continue
		//}

		//我也不太知道为啥放大之后效果更好!!! 现在知道了，只有在估计距离小于实际距离时候才可以达到整体最优
		lat := minItem[1] + offset[1]*step*ratio1
		lon := minItem[2] + offset[0]*step*ratio1

		//t2 := time.Now().UnixNano()

		latInt := int(math.Round(lat * cellP))
		lonInt := int(math.Round(lon * cellP))

		//作用不大
		_, isClose := closeMap[[2]int{
			latInt, lonInt,
		}]
		if isClose {
			list = append(list, []float64{999.0, 999.0})
			continue
		}
		//t22 := time.Now().UnixNano()
		//allT2 += int(t22 - t2)
		_, ok := costMap[[2]int{
			latInt, lonInt,
		}]

		if ok {
			list = append(list, []float64{utils.Float64Fixed(lat, n), utils.Float64Fixed(lon, n)})
			continue
		}

		//只在中间那段用地图大格子
		isLand := false

		//isBufferXiao := false

		if isOut {

			_, isLand = landMapBig[[2]int{
				int(lat*1000 + 1),
				int(lon * 1000),
			}]

		} else {
			//_, isLand = gangkouMap[[2]int{
			//	int(lat * cellP),
			//	int(lon * cellP),
			//}]
			for _, v := range GetMotions8(8) {
				_, isLandTep := gangkouMap[[2]int{
					int(lat*10000 + v[1]*2),
					int(lon*10000 + v[0]*2),
				}]

				if isLandTep {
					isLand = true
					break
				}
			}

		}

		if !isLand {
			list = append(list, []float64{utils.Float64Fixed(lat, 4), utils.Float64Fixed(lon, 4)})
		} else {
			//冲出缓冲区了再严格判断，如果有一个点还在地图上，进判断距离陆地太近，直接退出
			if isOut {
				inNum++
				//清空list
				//for i := 0; i < 34; i++ {
				//	list = append(list, [2]float64{99999.0, 99999.0})
				//}
				list = [][]float64{}
				break

				//list = append(list, []float64{999.0, 999.0})
			} else {
				list = append(list, []float64{999.0, 999.0})
			}

			//list = [][2]float64{}
			//
			//break
		}

	}
	if minItem[3] == 0 && isOut && len(list) != 0 {
		list = [][]float64{list[0]}
	}
	return list
}

var inNum = 0

// 对minItem进行正方形涂灰
//func paintGray(minItem []float64, grayMap map[[2]int]int, step, cellSize float64) {
//
//	//大格点版本+整数   和上面那个速度没区别
//	offset := 50
//	latInt := int(math.Round(minItem[1] * cellP))
//	lonInt := int(math.Round(minItem[2] * cellP))
//
//	for i := latInt - offset + 20; i <= latInt+offset; i += 10 {
//		for j := lonInt - offset + 10; j <= lonInt+offset-10; j += 10 {
//			//grayMap[[2]int{
//			//	i / 10,
//			//	j / 10,
//			//}] = struct{}{}
//			_, isGray := grayMap[[2]int{
//				i / 10,
//				j / 10,
//			}]
//			if !isGray {
//				grayMap[[2]int{
//					i / 10,
//					j / 10,
//				}] = 100
//			}
//
//		}
//	}
//}

func getDistance(lat1, lng1, lat2, lng2 float64) float64 {
	return math.Sqrt(math.Pow(lat1-lat2, 2) + math.Pow(lng1-lng2, 2))
	//zxDis := math.Sqrt(math.Pow(lat1-lat2, 2) + math.Pow(lng1-lng2, 2))
	//mhdDis := math.Abs(lat1-lat2) + math.Abs(lng1-lng2)
	////w := 1 + (zxDis)
	//return 0.4*mhdDis + 0.6*zxDis
	//	欧式距离
	//return math.Abs(lat1-lat2) + math.Abs(lng1-lng2)
}

func getDistanceWeight(lat1, lng1, lat2, lng2 float64, minItem, angleArr []float64) float64 {
	//angle := math.Atan2(lat2-lat1, lng2-lng1)
	//angle = angle * 180 / math.Pi
	//if angle < 0 {
	//	angle = 360 + angle
	//}
	////	计算lat2, lng2, minItem[1], minItem[2]连线的角度
	//angle2 := math.Atan2(minItem[1]-lat2, minItem[2]-lng2)
	//angle2 = angle2 * 180 / math.Pi
	//if angle2 < 0 {
	//	angle2 = 360 + angle2
	//}
	//angleDis := math.Abs(angle - angle2)
	//if angleDis > 180 {
	//	angleDis = 360 - angleDis
	//}
	//
	//if angleDis < 60 {
	//	return math.Sqrt(math.Pow(lat1-lat2, 2)+math.Pow(lng1-lng2, 2)) * 1
	//} else {
	//	return math.Sqrt(math.Pow(lat1-lat2, 2)+math.Pow(lng1-lng2, 2)) * 1
	//}

	//d := math.Sqrt(math.Pow(lat1-lat2, 2)+math.Pow(lng1-lng2, 2)) * 1
	//return d

	_, isBuffer := bufferMapTu[[2]int{
		int(math.Round(lat2 * 100)),
		int(math.Round(lng2 * 100)),
	}]

	if !isBuffer && minItem[3] != 0 {
		//list = append(list, []float64{999.0, 999.0})
		//continue
		return math.Sqrt(math.Pow(lat1-lat2, 2)+math.Pow(lng1-lng2, 2)) * 1.5
	} else {
		return math.Sqrt(math.Pow(lat1-lat2, 2)+math.Pow(lng1-lng2, 2)) * 1
	}
}

var maxAngle = 0.0

// 判断两点之间是否有障碍物
func isInLand(p1, p2 [2]int, landMap map[[2]int]struct{}) bool {
	// 获取直线路径上的所有点
	points := getPointsOnLine(p1, p2)

	// 检查每个点是否存在于陆地地图中
	for _, point := range points {
		if _, ok := landMap[point]; ok {
			return true
		}
	}

	return false
}

// 获取两点之间的直线路径上的所有点
// 获取两点之间的直线路径上的每隔5个单位取一个点
func getPointsOnLine(p1, p2 [2]int) [][2]int {
	points := make([][2]int, 15)

	// 提取两点的坐标
	x1, y1 := p1[0], p1[1]
	x2, y2 := p2[0], p2[1]

	//计算直线路径的总距离
	dx := abs(x2 - x1)
	dy := abs(y2 - y1)
	distance := max(dx, dy)

	// 计算每个单位距离的增量
	xIncrement := float64(x2-x1) / float64(distance)
	yIncrement := float64(y2-y1) / float64(distance)

	// 添加起始点
	points = append(points, [2]int{x1, y1})

	//每隔5个单位取一个点，并添加到结果列表中
	for i := 1; i <= distance; i += 10 {
		x := int(float64(x1) + float64(i)*xIncrement)
		y := int(float64(y1) + float64(i)*yIncrement)
		points = append(points, [2]int{x, y})
		//大格点版本
		//points = append(points, [2]int{x / 10, y / 10})
	}

	//x1, y1 := p1[0], p1[1]
	//x2, y2 := p2[0], p2[1]
	//dx := x2 - x1
	//dy := y2 - y1
	//for i := 1; i < 10; i++ {
	//	points = append(points, [2]int{(x1 + dx*i/10) / 10, (y1 + dy*i/10) / 10})
	//}

	return points
}

// 返回两个整数中的最大值
func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}

// 计算整数的绝对值
func abs(n int) int {
	if n < 0 {
		return -n
	}
	return n
}

// 根据relationMap获取路径
func getPath(relationMap map[[2]int][3]int, start, endMin, end [2]int, cellP float64, first bool, isOut bool) []string {
	var path [][2]int
	var result []string
	path = append(path, endMin)
	result = append(result, utils.Float64ToFixedStr(float64(end[0])/cellP, 4)+","+utils.Float64ToFixedStr(float64(end[1])/cellP, 4), "-1")
	//result = append(result, utils.Float64ToFixedStr(float64(endMin[0])/cellP, 4)+","+utils.Float64ToFixedStr(float64(endMin[1])/cellP, 4), "-1")

	angle := -1

	//维护一个抖动队列
	//var queue = []int{-1, -1, -1}

	for {

		//angle = relationMap[path[len(path)-1]][2]
		path = append(path, [2]int{
			relationMap[path[len(path)-1]][0],
			relationMap[path[len(path)-1]][1],
		})

		if relationMap[path[len(path)-1]][2] != angle {

			angle = relationMap[path[len(path)-1]][2]
			result = append(result, utils.Float64ToFixedStr(float64(path[len(path)-1][0])/cellP, 4)+","+utils.Float64ToFixedStr(float64(path[len(path)-1][1])/cellP, 4), strconv.Itoa(angle))
			//continue
		}
		if path[len(path)-1] == start {
			angle = relationMap[path[len(path)-1]][2]
			result = append(result, utils.Float64ToFixedStr(float64(start[0])/cellP, 4)+","+utils.Float64ToFixedStr(float64(start[1])/cellP, 4), strconv.Itoa(angle))
			break
		}

	}

	var finalResult []string
	finalResult = append(finalResult, result[0])
	motions := GetMotions(16)
	//tempArr:=[]string{"-2","-2","-2"}
	tempStr := []string{"", ""}
	var secondArr []float64
	var biaodaiArr []string
	var allArr []utils.LineStruct
	for i, _ := range result {
		if i%2 == 0 {
			//fmt.Println(i)
			finalResult = append(finalResult, result[i])
			lat := utils.StrToFloat64(strings.Split(result[i], ",")[0])
			lon := utils.StrToFloat64(strings.Split(result[i], ",")[1])

			//计算lat，lon和end的角度
			angle1 := -1.0
			angleIdx := utils.StrToFloat64(result[i+1])
			if angleIdx == 0 || angleIdx == -1 {
				angle1 = math.Atan2(float64(end[0])-lat, float64(end[1])-lon) * 180 / math.Pi
			} else {
				angle1 = math.Atan2(motions[int(angleIdx)][1], motions[int(angleIdx)][0]) * 180 / math.Pi
			}

			if angle1 < 0 {
				angle1 = 360 + angle1
			}

			line := utils.LineStruct{
				Lat:      lat,
				Lon:      lon,
				Angle:    angleIdx,
				AngleNum: angle1,
			}
			allArr = append(allArr, line)
			continue
			if i > 0 && i < len(result)/2-1 {
				//fmt.Println(result[i-1], result[i+3])
				if result[i-1] == result[i+3] {
					if len(biaodaiArr) == 0 {
						biaodaiArr = append(biaodaiArr, result[i-2])
					}
					biaodaiArr = append(biaodaiArr, result[i])
					//fmt.Println(result[i-1], result[i+3])
				} else {
					fmt.Println(biaodaiArr, result[i])
					if len(biaodaiArr) > 0 {
						pointArr := strings.Split(biaodaiArr[0], ",")
						pointArr1 := strings.Split(result[i], ",")
						req := HtAStarReq{
							End:   []float64{utils.StrToFloat64(pointArr[0]), utils.StrToFloat64(pointArr[1])},
							Start: []float64{utils.StrToFloat64(pointArr1[0]), utils.StrToFloat64(pointArr1[1])},
						}
						tempFinal := findOnePath(req, 16, 0.005, true, false, false)
						finalResult = append(finalResult, tempFinal...)
						biaodaiArr = []string{}
					} else {
						finalResult = append(finalResult, result[i])
					}
				}
			} else if i == len(result)/2-1 {

			}
			continue
			canzhao := ""
			if len(result)-i < 6 {
				if i > 1 {
					canzhao = result[i-3]
				} else {
					finalResult = append(finalResult, result[i])
					continue
				}
			} else {
				canzhao = result[i+5]
			}
			//fmt.Println(result[i+1], result[i+5])
			if result[i+1] != canzhao {
				finalResult = append(finalResult, result[i])
				fmt.Println(result[i], result[i+1])
				//fmt.Println(result[i], result[i+1])
			} else {
				fmt.Println(result[i], result[i+1])
				finalResult = append(finalResult, result[i])
				continue
				if result[i+1] == tempStr[1] || result[i+3] == tempStr[0] {
					tempStr[0], tempStr[1] = result[i+1], result[i+3]
				} else {
					tempStr[0], tempStr[1] = result[i+1], result[i+3]
					//finalResult = append(finalResult, result[i])
					//fmt.Println(result[i])
					pointArr := strings.Split(result[i], ",")
					secondArr = append(secondArr, utils.StrToFloat64(pointArr[0]))
					secondArr = append(secondArr, utils.StrToFloat64(pointArr[1]))
					if len(secondArr) == 4 {
						req := HtAStarReq{
							End:   []float64{secondArr[0], secondArr[1]},
							Start: []float64{secondArr[2], secondArr[3]},
						}
						secondArr = []float64{}
						//findOnePath(req, 16, 0.005, true, false)
						tempFinal := findOnePath(req, 16, 0.005, true, false, false)
						finalResult = append(finalResult, tempFinal...)
						//fmt.Println(finalResult)
					}
				}
			}
		}
	}

	//fmt.Println("allArr", allArr)
	r, pt := utils.MergeSame(allArr)
	if first {
		rrRusult := []string{}
		idx := 0
		for _, v := range pt {

			if len(v) > 0 {
				//positionStr := utils.Float64ToFixedStr(v[0].Lat, 4) + "," + utils.Float64ToFixedStr(v[0].Lon, 4)
				//finalResult = append(finalResult, positionStr)
				//rrRusult = append(rrRusult, positionStr)
				for _, v1 := range v {
					rrRusult = append(rrRusult, utils.Float64ToFixedStr(v1.Lat, 4)+","+utils.Float64ToFixedStr(v1.Lon, 4))
				}
			} else {
				if len(r[idx]) < 3 {
					continue
				}
				th := r[idx]
				idx++
				//	重新找
				req := HtAStarReq{
					End:   []float64{th[0].Lat, th[0].Lon},
					Start: []float64{th[len(th)-1].Lat, th[len(th)-1].Lon},
				}
				tempFinal := findOnePath(req, 16, 0.005, isOut, false, false)
				//fmt.Println("tempFinal", tempFinal)
				for _, v1 := range tempFinal {
					rrRusult = append(rrRusult, v1)
				}
			}
		}
		return rrRusult
	}

	return finalResult
}

// getPointBuffer 算出起始点和目标点的缓冲区外点。如果本身就在缓冲区外就不用算了
func getPointBuffer(req *HtAStarReq, step float64) ([]float64, []float64) {
	//var motions [][2]float64
	//angle := 32
	//每次扩展的长度
	//step := 0.005
	//for i := 0; i < angle; i++ {
	//	motions = append(motions, [2]float64{math.Cos(float64(i) * 2 * math.Pi / float64(angle)), math.Sin(float64(i) * 2 * math.Pi / float64(angle))})
	//}

	motions := GetMotions(16)
	motions = motions[1:]
	//删除motions第一个元素

	var startBuffer []float64
	var endBuffer []float64
	wgBuffer := sync.WaitGroup{}
	wgBuffer.Add(2)
	for i, v := range [2][]float64{req.Start, req.End} {
		go func(v []float64, i int) {
			if i == 0 {
				//startBuffer = func1Five(motions, step, [][]float64{v}, req.End)
				//var ch1 = make(chan []float64, 10)
				//ch1 <- []float64{v[0], v[1], -1}
				//close(ch1)
				////grayStart := make(map[[2]int]int, 2000)
				//grayStart := sync.Map{}
				//
				//startBuffer = func1(motions, step, ch1, req.End, &grayStart, req.Start)
				startBuffer = func8(motions, step, map[[2]float64]int{
					{v[0], v[1]}: 1,
				}, req.End, &sync.Map{}, req.Start)
				//_, isLand := landMapBig[[2]int{
				//	int(v[0]*1000 + 1),
				//	int(v[1] * 1000),
				//}]
				//if !isLand {
				//	startBuffer = func8(motions, step, v, req.End)
				//} else {
				//	startBuffer = v
				//}

			} else {
				//endBuffer = func1Five(motions, step, [][]float64{v}, req.Start)
				//var ch1 = make(chan []float64, 10)
				//ch1 <- []float64{v[0], v[1], -1}
				//close(ch1)
				//grayEnd := sync.Map{}
				//endBuffer = func1(motions, step, ch1, req.Start, &grayEnd, req.End)

				endBuffer = func8(motions, step, map[[2]float64]int{
					{v[0], v[1]}: 1,
				}, req.Start, &sync.Map{}, req.End)

				//endBuffer = func8(motions, step, v, req.Start)

				//_, isLand := landMapBig[[2]int{
				//	int(v[0]*1000 + 1),
				//	int(v[1] * 1000),
				//}]
				//if !isLand {
				//	endBuffer = func8(motions, step, v, req.Start)
				//} else {
				//	endBuffer = v
				//}
			}
			wgBuffer.Done()
		}(v, i)
	}
	wgBuffer.Wait()
	return startBuffer, endBuffer
}

func forward(motions [][2]float64, point []float64, angleIdx int, step float64) bool {
	for _, offset := range motions {
		lat := point[0] + offset[1]*step
		lon := point[1] + offset[0]*step

		_, isLand := landMapBig[[2]int{
			int(lat*1000 + 1),
			int(lon * 1000),
		}]
		if isLand {
			return true
		}
	}
	return false
}

func func8(motions [][]float64, step float64, points map[[2]float64]int, oPoint []float64, gray *sync.Map, start []float64) []float64 {
	var tempMap = make(map[[2]float64]int)
	var okPoints [][]float64

	for point := range points {
		landNum1 := 0
		for _, offset := range motions {
			lat := point[0] + offset[1]*step
			lon := point[1] + offset[0]*step
			_, isLand := landMapBig[[2]int{
				int(lat*1000 + 1),
				int(lon * 1000),
			}]

			if !isLand {
				tempMap[[2]float64{
					utils.Float64Fixed(lat, 4),
					utils.Float64Fixed(lon, 4),
				}] = 1
			} else {
				landNum1++
			}
		}
		if landNum1 == 0 {

			if len(points) == 1 {
				okPoints = append(okPoints, []float64{point[0], point[1], getDistance(point[0], point[1], oPoint[0], oPoint[1])})

			} else {
				angle := math.Atan2(point[0]-start[0], point[1]-start[1]) * 180 / math.Pi
				if angle < 0 {
					angle += 360
				}
				if angle >= 200 && angle <= 360 {
					okPoints = append(okPoints, []float64{point[0], point[1], getDistance(point[0], point[1], oPoint[0], oPoint[1])})
				}
			}
		}
	}

	if len(okPoints) != 0 {
		minDis := okPoints[0]
		for _, v := range okPoints {
			if v[2] < minDis[2] {
				minDis = v
			}
		}
		return []float64{minDis[0], minDis[1]}
	} else {
		return func8(motions, step, tempMap, oPoint, gray, start)
	}
}

func func1(motions [][]float64, step float64, points chan []float64, oPoint []float64, gray *sync.Map, start []float64) []float64 {

	var tempPoints = make(chan []float64, len(points)*32)
	var okPoints = make(chan []float64, len(points))
	var ch1 = make(chan []float64, len(points))
	var wgFunc1 sync.WaitGroup

	wgFunc1.Add(1)
	go func() {
		for point := range points {
			ch1 <- point
		}
		wgFunc1.Done()
		close(ch1)
	}()

	for i := 0; i < 2; i++ {
		wgFunc1.Add(1)
		go func() {
			defer wgFunc1.Done()
			for point := range ch1 {
				landNum1 := 0
				for idx, offset := range motions {
					lat := point[0] + offset[1]*step
					lon := point[1] + offset[0]*step
					_, isLand := landMapBig[[2]int{
						int(lat*1000 + 1),
						int(lon * 1000),
					}]
					if !isLand {

						grayNum1, isGray := gray.Load([2]int{
							int(lat*1000 + 1),
							int(lon * 1000),
						})
						if !isGray {
							tempPoints <- []float64{lat, lon, float64(idx)}
							//gray[[2]int{
							//	int(lat*1000 + 1),
							//	int(lon * 1000),
							//}] = 0
							gray.Store([2]int{
								int(lat*1000 + 1),
								int(lon * 1000),
							}, 0)
						} else {
							//第二个用到浓度的地方，20这个数随便整的
							if grayNum1.(int) < 20 {
								tempPoints <- []float64{lat, lon, float64(idx)}
								gray.Store([2]int{
									int(lat*1000 + 1),
									int(lon * 1000),
								}, grayNum1.(int)+1)
							}
						}

					} else {
						landNum1++
					}
				}
				//如果其中一个点可以，暂时保存
				if landNum1 == 0 {
					//计算point和start的夹角
					angle := math.Atan2(point[0]-start[0], point[1]-start[1]) * 180 / math.Pi
					if angle < 0 {
						angle += 360
					}
					//fmt.Println("angle:", angle)
					if angle >= 200 && angle <= 360 {
						okPoints <- []float64{point[0], point[1], getDistance(point[0], point[1], oPoint[0], oPoint[1])}
					}
				}
			}
		}()
	}

	//打印wgFunc1的数量
	wgFunc1.Wait()

	if len(okPoints) != 0 {
		close(okPoints)
		minDis := <-okPoints
		for v := range okPoints {
			if v[2] < minDis[2] {
				minDis = v
			}
		}
		return []float64{minDis[0], minDis[1]}
	} else {
		close(tempPoints)
		return func1(motions, step, tempPoints, oPoint, gray, start)
	}
}

// 获取最近的一个非陆地点
func getNotLan(point, oPoint []float64) []float64 {
	//36.0920 120.3171
	//if point[0] == 36.0921 && point[1] == 120.3206 {
	//	return []float64{36.0841, 120.2910}
	//}
	var motions [][2]float64
	angle := 32
	for i := 0; i < angle; i++ {
		motions = append(motions, [2]float64{math.Cos(float64(i) * 2 * math.Pi / float64(angle)), math.Sin(float64(i) * 2 * math.Pi / float64(angle))})
	}
	return get1(motions, 0.001, point, oPoint)
}

func get1(motions [][2]float64, step float64, point []float64, oPoint []float64) []float64 {
	var okPoints [][]float64
	for _, offset := range motions {
		lat := point[0] + offset[1]*step
		lon := point[1] + offset[0]*step

		_, isLand := gangkouMap[[2]int{
			int(lat * 10000),
			int(lon * 10000),
		}]

		if !isLand {
			okPoints = append(okPoints, []float64{lat, lon})
		}
	}

	if len(okPoints) != 0 {
		minDis := okPoints[0]
		for _, v := range okPoints {
			if getDistance(v[0], v[1], oPoint[0], oPoint[1]) < getDistance(minDis[0], minDis[1], oPoint[0], oPoint[1]) {
				minDis = v
			}
		}
		return minDis
	} else {
		return get1(motions, step+0.001, point, oPoint)
	}
}

func readLandTxt(name string) map[[2]int]struct{} {
	m := make(map[[2]int]struct{}, 250000)
	f1, _ := os.Open(name)
	scanner := bufio.NewScanner(f1)
	for scanner.Scan() {
		line := scanner.Text()
		lat, _ := strconv.ParseFloat(strings.Split(line, ",")[0], 64)
		lon, _ := strconv.ParseFloat(strings.Split(line, ",")[1], 64)
		m[[2]int{
			int(lat),
			int(lon),
		}] = struct{}{}

	}
	f1.Close()

	return m
}

func readGangkouMap() map[[2]int]struct{} {
	m := make(map[[2]int]struct{}, 250000*3)
	fileNames := []string{"36.1_120.3.txt", "36.2_120.3.txt", "35.4_119.5.txt", "36.2_120.5.txt"}
	for _, fileName := range fileNames {
		//m1 := readLandTxt("./public/image/0.05/"+fileName)
		f1, _ := os.Open("./public/image/0.05/" + fileName)
		scanner := bufio.NewScanner(f1)
		for scanner.Scan() {
			line := scanner.Text()
			lat, _ := strconv.ParseFloat(strings.Split(line, ",")[0], 64)
			lon, _ := strconv.ParseFloat(strings.Split(line, ",")[1], 64)
			m[[2]int{
				int(lat),
				int(lon),
			}] = struct{}{}
		}
		f1.Close()
	}
	return m
}
